<?php

/**
 * LDAP helper class.
 * 
 * Implemented as singleton.
 * 
 * @author Volker Kueffel <volker.kueffel@gmail.com>
 * @version $Id: LDAPConnector.class.php 18 2009-01-05 02:18:30Z volker.kueffel $
 */
class LDAPConnector {
	
	private static $instance=null;
	
	private $connection=null;
	private $connectDN=null;
	private $connectPW=null;
	private $baseDN=null;
	
	/**
	 * Initalize and return LDAP connector.
	 * 
	 * This method needs to be called first before using
	 * the instance.
	 * 
	 * @param array $config configuration parameters
	 * 
	 * @return LDAPConnector the connector instance
	 */
	public static function init($config) {
		if (!self::$instance) {
    		$class=__CLASS__;
    		self::$instance=new $class();
			self::$instance->configure($config);
		}
		return self::$instance;
	}
	


    public static function getInstance() {
    	if (!self::$instance) throw new Exception(__CLASS__.' not initialized');
    	return self::$instance;
    }

	/**
	 * Singleton, constructor is private.
	 */	
    private function __construct() {
    }
    
    
    private function configure($config) {
    	$ldapUrl='ldap';
    	if (array_key_exists('secure',$config) && $config['secure']) {
    		$ldapUrl.='s';
    	}
		$ldapUrl.='://'.$config['host'];
		$this->connectDN=$config['connectDN'];
		$this->connectPW=$config['connectPW'];
		$this->baseDN=trim(preg_replace('/\s*,\s*/',',',$config['baseDN']));  // no blanks
		$this->connection=@ldap_connect($ldapUrl);
		if ($this->connection) {
			@ldap_set_option($this->connection,LDAP_OPT_PROTOCOL_VERSION,3);
			$bindResult = ldap_bind($this->connection, $this->connectDN, $this->connectPW);			
		}

    }
    
    
	public function cleanUpEntry( $entry ) {
	    $retEntry = array();
	    for ( $i = 0; $i < $entry['count']; $i++ ) {
	        $attribute = $entry[$i];
	        if ( $entry[$attribute]['count'] == 1 ) {
	            $retEntry[$attribute] = $entry[$attribute][0];
	        } else {
	            for ( $j = 0; $j < $entry[$attribute]['count']; $j++ ) {
	                $retEntry[$attribute][] = $entry[$attribute][$j];
	            }
	        }
	    }
	    return $retEntry;
	}

	public function ldap2Array($info) {
		$result=array();
		if (is_array($info) && array_key_exists('count',$info)) {
			for ($i=0; $i<$info['count']; $i++) {
				$entry=$this->cleanUpEntry($info[$i]);
				if (is_array($entry) && array_key_exists('dn',$info[$i])) {
					$entry['dn']=$info[$i]['dn'];
				}
				$result[]=$entry;
			}
		}
		return $result;
	}

	public function extractSubDN($dn,$parentDN=null) {
		if ($parentDN===null) $parentDN=$this->baseDN;
		$subDn='';
		$pos=strrpos($dn,$parentDN);
		if ($pos>0) {
			$subDn=substr($dn,0,$pos-1);
		}
		return $subDn;
	}

	
	
	public function rawQuery($dn,$filter=null,$attributes=array()) {	
		$entries=null;
		$sr=@ldap_search($this->connection, $dn, $filter,$attributes);
		if ($sr) {
			$entries = @ldap_get_entries($this->connection, $sr);
		}
		return $entries;
	}


	public function query($dn,$filter=null,$attributes=array()) {	
		$result=array();
		$entries=$this->rawQuery($dn,$filter,$attributes);	
		if ($entries) {
			$result=$this->ldap2Array($entries);
		}
		return $result;
	}
	
	
	public function getFullDN($subDN,$baseDN=null) {
		if ($baseDN===null) {
			$baseDN=$this->baseDN;	
		} else {
			$baseDN=preg_replace('/\s*,\s*/',',',$baseDN);
		}
		$dn=preg_replace('/\s*,\s*/',',',$subDN).','.$baseDN;
		return $dn;
	}
	
	
	public function getBaseDN() {
		return $this->baseDN;
	}
    
}
?>